Skip to content

Comments

Add per-user submission rate limit (1 per hour)#436

Merged
S1ro1 merged 1 commit intomainfrom
per-user-submission-rate-limit
Feb 7, 2026
Merged

Add per-user submission rate limit (1 per hour)#436
S1ro1 merged 1 commit intomainfrom
per-user-submission-rate-limit

Conversation

@msaroufim
Copy link
Member

Enforce a global per-user rate limit of 1 submission per hour across all leaderboards and modes. The 429 response suggests using the NVIDIA runner instead of Modal for faster iteration.

Copilot AI review requested due to automatic review settings February 7, 2026 17:27
@github-actions
Copy link

github-actions bot commented Feb 7, 2026

Coverage report

Click to see where and how coverage changed

FileStatementsMissingCoverageCoverage
(new stmts)
Lines missing
  src/libkernelbot
  leaderboard_db.py
  utils.py
Project Total  

This report was generated by python-coverage-comment-action

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a global per-user submission rate limit (1 submission per hour) enforced at the API layer, backed by a new database query to detect recent submissions.

Changes:

  • Added LeaderboardDB.check_user_rate_limit() to fetch a user’s most recent submission within a configurable time window.
  • Enforced the per-user limit in to_submit_info() by returning HTTP 429 with guidance about using the NVIDIA runner.
  • Added unit tests covering the DB rate-limit query and API behavior under rate-limited vs allowed conditions.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
tests/test_leaderboard_db.py Adds DB-level tests for the new per-user rate limit query.
tests/test_admin_api.py Adds API tests asserting 429 on repeat submissions and non-429 on first submission.
src/libkernelbot/leaderboard_db.py Introduces check_user_rate_limit() query used by the API to enforce the window.
src/kernelbot/api/api_utils.py Enforces the per-user rate limit and returns 429 with a helpful client-facing message.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 221 to 225
except Exception as e:
raise HTTPException(
status_code=500,
detail=f"Internal server error while checking rate limit: {e}",
) from e
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 500-path includes the raw exception message in the HTTP response (...: {e}). This can leak internal details to clients. Prefer logging the exception server-side and returning a generic error message (optionally with a request ID) instead.

Copilot uses AI. Check for mistakes.
Comment on lines +1179 to +1186
"""
SELECT submission_time
FROM leaderboard.submission
WHERE user_id = %s
AND submission_time > NOW() - INTERVAL '%s hours'
ORDER BY submission_time DESC
LIMIT 1
""",
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new rate-limit query filters on (user_id, submission_time) but there’s no supporting index in the schema migrations (currently only an index on submission(leaderboard_id)). At scale this will devolve into scanning many rows per request. Add a DB migration to create an index such as (user_id, submission_time DESC) (or (user_id, submission_time)) to keep the check fast.

Copilot uses AI. Check for mistakes.
Comment on lines 208 to 218
with db_context as db:
last_submission_time = db.check_user_rate_limit(user_id)
if last_submission_time:
raise HTTPException(
status_code=429,
detail=(
f"Rate limit exceeded. You can submit once per hour. "
f"Last submission: {last_submission_time.isoformat()}. "
f"Consider using the NVIDIA runner instead of Modal for faster iteration."
),
)
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to_submit_info opens db_context twice (once for rate limiting, again for leaderboard/GPU validation). Because LeaderboardDB.__exit__ disconnects when refcount hits 0, this will connect/disconnect twice per request. Consider using a single with db_context as db: block for both checks to avoid extra connection overhead and reduce failure points.

Suggested change
with db_context as db:
last_submission_time = db.check_user_rate_limit(user_id)
if last_submission_time:
raise HTTPException(
status_code=429,
detail=(
f"Rate limit exceeded. You can submit once per hour. "
f"Last submission: {last_submission_time.isoformat()}. "
f"Consider using the NVIDIA runner instead of Modal for faster iteration."
),
)
last_submission_time = db_context.check_user_rate_limit(user_id)
if last_submission_time:
raise HTTPException(
status_code=429,
detail=(
f"Rate limit exceeded. You can submit once per hour. "
f"Last submission: {last_submission_time.isoformat()}. "
f"Consider using the NVIDIA runner instead of Modal for faster iteration."
),
)

Copilot uses AI. Check for mistakes.
@msaroufim msaroufim force-pushed the per-user-submission-rate-limit branch from d3c86d1 to 8017fef Compare February 7, 2026 17:33
Enforce a per-user rate limit of 1 submission per hour, scoped to Modal
B200 GPU submissions on leaderboard ID 730 only. The 429 response suggests
using the NVIDIA runner instead of Modal for faster iteration.
@msaroufim msaroufim force-pushed the per-user-submission-rate-limit branch from 8017fef to 2c3fb71 Compare February 7, 2026 17:35
@S1ro1 S1ro1 merged commit 7d97a31 into main Feb 7, 2026
5 checks passed
msaroufim added a commit that referenced this pull request Feb 8, 2026
msaroufim added a commit that referenced this pull request Feb 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants